package com.mobile.chench.myvpnapplication;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.VpnService;
import android.os.Build;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.text.format.DateUtils;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * @author: chenxh
 * @date: 2021/9/14
 */
public class MyVPNService extends VpnService {


    /* The IP address of the virtual network interface */
    public static final String VPN_IP_ADDRESS = "10.215.173.1";
    public static final String VPN_IP6_ADDRESS = "fd00:2:fd00:1:fd00:1:fd00:1";

    public static final String FALLBACK_DNS_SERVER = "8.8.8.8";
    public static final String IPV6_DNS_SERVER = "2001:4860:4860::8888";
    private ParcelFileDescriptor mParcelFileDescriptor;

    @Override
    public void onCreate() {
        super.onCreate();
        VpnService.Builder builder = new VpnService.Builder();

        //1 、要过滤的APP uid *不是包名
        // String pkName = "com.baidu.searchbox";
        // String pkName = "com.hexin.plat.android.ZhongyuanSecurity";
        // String pkName = "com.taobao.taobao";
        // String pkName = "com.mobile.chench.myvpnapplication";
        String pkName = "com.dfzq.winner";
        int uid = 0;
        try {
            uid = getPackageManager().getApplicationInfo(pkName, 0).uid;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        // Create a local TUN interface using predetermined addresses. In your app,
        // you typically use values returned from the VPN gateway during handshaking.
        try {
            mParcelFileDescriptor = builder
                    // ipv4
                    .addAddress(VPN_IP_ADDRESS, 30)
                    .addRoute("0.0.0.0", 0)
                    // .addRoute("128.0.0.0", 0)
                    .addDnsServer("192.168.1.1")
                    // ipv6
                    .addAddress(VPN_IP6_ADDRESS, 128)
                    .addRoute("::", 3)
                    .addDnsServer(InetAddress.getByName(IPV6_DNS_SERVER))
                    // 过滤应用
                    .addAllowedApplication(String.valueOf(uid))

                    .establish();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("chenxh","ee"+e.getMessage());
        }

        if (mParcelFileDescriptor != null) {
            int fd = mParcelFileDescriptor.getFd();
            Log.e("chenxh", "fd = " + fd);
            // try {
                // runVpnConnection();
            // } catch (Exception e) {
            //     e.printStackTrace();
            // }

        }
        Log.e("chenxh", "MyVPNService onCreate " + " 过滤包：" + pkName + "," + uid + ";");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("chenxh", "MyVPNService onStartCommand");

        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onRevoke() {
        super.onRevoke();
        Log.e("chenxh", "MyVPNService onRevoke");

    }

    @Override
    public boolean protect(int socket) {
        Log.e("chenxh","socket"+socket);
        return super.protect(socket);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("chenxh", "MyVPNService onDestroy");
        try {
            mParcelFileDescriptor.closeWithError("onDestroy");
            mParcelFileDescriptor.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private void runVpnConnection() throws Exception {

        FileInputStream in = new FileInputStream(mParcelFileDescriptor.getFileDescriptor());

        // Allocate the buffer for a single packet.
        ByteBuffer packet = ByteBuffer.allocate(512*1024);

        // We keep forwarding packets till something goes wrong.
        while (true) {
            // Assume that we did not make any progress in this iteration.
            boolean idle = true;

            // Read the outgoing packet from the input stream.
            int length = in.read(packet.array());
            if (length > 0) {

                Log.i("chenxh","************new packet");
                // System.exit(-1);
                while (packet.hasRemaining()) {
                    Log.i("chenxh",""+packet.getInt());
                    //System.out.print((char) packet.get());
                }
                packet.limit(length);
                //  tunnel.write(packet);
                packet.clear();

                // There might be more outgoing packets.
                idle = false;
            }
            Thread.sleep(50);
        }
    }

    public String getCaptureFile() {
        /**
         * 抓包数据文件夹路径
         */
        String BASE_LOG_PATH_SDCARD_DIR =
                Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test" + File.separator + "capture" + File.separator;

        return BASE_LOG_PATH_SDCARD_DIR + "_" + getDateTimeNo2String();
    }

    public SimpleDateFormat simpleDateTimeFormatNo2 = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault());

    /**
     * 获取当前时间 {yyyyMMdd_HHmmss}
     */
    public String getDateTimeNo2String() {
        return simpleDateTimeFormatNo2.format(new Date());
    }

}
